package jsu.yym.tiktok.service;

import jsu.yym.tiktok.pojo.ResponseResult;
import jsu.yym.tiktok.pojo.User;
import jsu.yym.tiktok.pojo.Video;;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import jsu.yym.tiktok.mapper.Type;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class SearchService {


    //在es中实现模糊查找视频
    public List<Video> searchVideByEs(String keyword) throws IOException {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost", 9200, "http")));
        SearchRequest searchRequest = new SearchRequest("video");

        // 创建一个布尔查询，同时匹配 context 和 label 字段
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        MatchQueryBuilder contextQuery = QueryBuilders.matchQuery("context", keyword).fuzziness(Fuzziness.ONE);
        MatchQueryBuilder labelQuery = QueryBuilders.matchQuery("label", keyword).fuzziness(Fuzziness.ONE);

        // 使用should方法将 contextQuery 和 labelQuery 添加到布尔查询中
        boolQuery.should(contextQuery);
        boolQuery.should(labelQuery);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQuery);

        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();

        // 将搜索结果转换为 Video 对象
        List<Video> videos = new ArrayList<>();
        for (SearchHit hit : hits) {
            Video video = new Video();
            video.setContext((String) hit.getSourceAsMap().get("context"));
            video.setLabel(changeLabel((String) hit.getSourceAsMap().get("label")));
            video.setImgUser((String)hit.getSourceAsMap().get("imgUser"));
            video.setSrc((String) hit.getSourceAsMap().get("src"));
            video.setImage((String) hit.getSourceAsMap().get("image"));
            video.setUsername((String) hit.getSourceAsMap().get("username"));
            video.setPkId((Integer)hit.getSourceAsMap().get("pkId"));
            video.setState((Integer) hit.getSourceAsMap().get("state"));
            video.setCount((Integer) hit.getSourceAsMap().get("count"));
            video.setShares((Integer) hit.getSourceAsMap().get("shares"));
            video.setCollections((Integer) hit.getSourceAsMap().get("collections"));
            video.setFileName((String) hit.getSourceAsMap().get("fileName"));

            // 解析其他字段...
            videos.add(video);
        }

        // 根据匹配度从高到低排序（这里假定匹配度越高，context 长度越长）
        videos.sort((v1, v2) -> {
            int len1 = v1.getContext().length();
            int len2 = v2.getContext().length();
            return Integer.compare(len2, len1);
        });

        // 关闭Elasticsearch客户端连接
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return videos;
    }

    public String changeLabel(String label){
        String type = null;
        switch (label){
            case Type.SPORTS :type="体育运动";break;
            case Type.DAILY :type="生活日常";break;
            case Type.FILM_MUSIC: type="音乐FM";break;
            case Type.STAR_GOSSIP: type="明星影视";break;
            case Type.FOOD_SHOP: type="美食探店";break;
            case Type.GAME_FICTION: type="游戏小说";break;
        }
        return type;
    }

    public String transLabel(String label){
        String type = null;
        switch (label){
            case "体育运动" :type=Type.SPORTS;break;
            case "生活日常" :type=Type.DAILY;break;
            case "音乐FM": type=Type.STAR_GOSSIP;break;
            case "明星影视": type=Type.FILM_MUSIC;break;
            case "美食探店": type=Type.FOOD_SHOP;break;
            case "游戏小说": type=Type.GAME_FICTION;break;
        }
        return type;
    }

    //在es中模糊查找用户
    public List<User> searchUsersByEs(String keyword) throws IOException {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost", 9200, "http")));
        SearchRequest searchRequest = new SearchRequest("user");

        // 创建一个布尔查询，同时匹配 nickname、username 和 signature 字段
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        MatchQueryBuilder nicknameQuery = QueryBuilders.matchQuery("nickname", keyword).fuzziness(Fuzziness.ONE);
        MatchQueryBuilder usernameQuery = QueryBuilders.matchQuery("username", keyword).fuzziness(Fuzziness.ONE);
        MatchQueryBuilder signatureQuery = QueryBuilders.matchQuery("signature", keyword).fuzziness(Fuzziness.ONE);

        // 使用should方法将查询条件添加到布尔查询中
        boolQuery.should(nicknameQuery);
        boolQuery.should(usernameQuery);
        boolQuery.should(signatureQuery);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQuery);

        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();

        // 将搜索结果转换为 User 对象
        List<User> users = new ArrayList<>();
        for (SearchHit hit : hits) {
            User user = new User();
            user.setNickname((String) hit.getSourceAsMap().get("nickname"));
            user.setUsername((String) hit.getSourceAsMap().get("username"));
            user.setSignature((String) hit.getSourceAsMap().get("signature"));
            user.setPassword((String) hit.getSourceAsMap().get("password"));
            user.setEmail((String) hit.getSourceAsMap().get("email"));
            user.setSex((String) hit.getSourceAsMap().get("sex"));
            user.setImage((String) hit.getSourceAsMap().get("image"));
            user.setAddress((String) hit.getSourceAsMap().get("address"));
            user.setTarge((String) hit.getSourceAsMap().get("targe"));
            user.setState((Integer) hit.getSourceAsMap().get("state"));

            // 解析其他字段...
            users.add(user);
        }

        // 根据匹配度从高到低排序（可以根据需要更改排序条件）
        users.sort((u1, u2) -> {
            // 你可以根据匹配度或其他条件进行排序
            // 这里假定匹配度越高，nickname 长度越长
            int len1 = u1.getNickname().length();
            int len2 = u2.getNickname().length();
            return Integer.compare(len2, len1);
        });

        // 关闭 Elasticsearch 客户端连接
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return users;
    }


    //在es中获取搜索热词
    public ResponseResult getTopNHotTerms() throws IOException {
        List<String> hotTerms = new ArrayList<>();
        System.out.println("111");
        // 获取 user 索引中的热词
        hotTerms.addAll(getTopNHotTermsFromIndex("user", "username", "nickname", "signature"));
        System.out.println("222");
        // 获取 video 索引中的热词
        hotTerms.addAll(getTopNHotTermsFromIndex("video", "context", "label"));
        System.out.println("333");
        // 返回前十名热词
        if (hotTerms.size() > 10) {
            hotTerms= hotTerms.subList(0, 7);
        }
        if (Objects.isNull(hotTerms)) {
            return new ResponseResult(409,"暂时还没有搜索记录");
        }
        return new ResponseResult(200,"成功获取",hotTerms);
    }

    private List<String> getTopNHotTermsFromIndex(String indexName, String... fields) throws IOException {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost", 9200, "http")));
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();



        // 使用聚合来获取热词
        sourceBuilder.size(0); // 禁用_source，只获取聚合信息
        for (String field : fields) {
            sourceBuilder.aggregation(AggregationBuilders
                    .terms("hot_terms_" + field)
                    .field(field + ".keyword")  // 使用 .keyword 后缀来引用 keyword 子字段
                    .size(10));
        }

        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 提取热词
        List<String> hotTerms = new ArrayList<>();

        Aggregations aggregations = searchResponse.getAggregations();
        for (String field : fields) {
            // 使用正确的类型 ParsedStringTerms
            ParsedStringTerms terms = aggregations.get("hot_terms_" + field);
            for (Terms.Bucket bucket : terms.getBuckets()) {
                hotTerms.add(bucket.getKeyAsString());
            }

        }
        // 关闭 Elasticsearch 客户端连接
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return hotTerms;
    }




}
